package com.wgchao.amc.service.impl;

import com.wgchao.amc.autho.AuthoInfoCenter;
import com.wgchao.amc.common.*;
import com.wgchao.amc.entity.base.*;
import com.wgchao.amc.mapstruct.dto.SysBaseRoleDTO;
import com.wgchao.amc.mapstruct.mapper.expand.SysBaseRoleMapperExpand;
import com.wgchao.amc.repository.base.*;
import com.wgchao.amc.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @ClassName: RoleServiceImpl
 * @author: wgchao
 * @createTime: 2019/10/29 10:53 AM
 * @Description: 角色管理
 */
@Service
@Transactional
public class RoleServiceImpl implements RoleService {
    @Autowired
    private SysBaseRoleRepository roleRepository;
    @Autowired
    private SysBaseRoleMapperExpand roleMapperExpand;
    @Autowired
    private SysBaseAgencyRepository agencyRepository;
    @Autowired
    private SysBaseGroupRepository groupRepository;
    @Autowired
    private SysBaseGrRepository grRepository;
    @Autowired
    private SysBaseUrRepository urRepository;


    /**
     * 新增角色
     * @param roleDTO
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<SysBaseRoleDTO> save(SysBaseRoleDTO roleDTO, AuthoInfoCenter authoInfoCenter) throws Exception {
        EvaluateInfo evaluateInfo = evaluate(roleDTO, roled -> {
            SysBaseRoleDTO roleDTO1 = (SysBaseRoleDTO) roled;
            Optional<SysBaseAgency> agencyOptional = agencyRepository.findById(roleDTO1.getAgencyCode());
            if(!agencyOptional.isPresent()){
                return new EvaluateInfo(false, "机构不存在");
            }
            SysBaseAgency agency = agencyOptional.get();
            if(agency.isDel()){
                return new EvaluateInfo(false, "机构已删除");
            }
            if(agency.isCancel()){
                return new EvaluateInfo(false, "机构已注销");
            }
            SysBaseRole role = roleRepository.findFirstByRoleNameAndAgencyCode(roleDTO1.getRoleName(), roleDTO1.getAgencyCode());
            if(role != null){
                return new EvaluateInfo(false, "机构已存在该角色");
            }
            return new EvaluateInfo(true, null);
        });
        if(!evaluateInfo.isSuccess()){
            return ResultCommon.fail(evaluateInfo.getMsg());
        }

        SysBaseRole role = roleMapperExpand.toEntity(roleDTO);
        role.setCreateTime(new Date());
        role.setCreateUser(authoInfoCenter.getUserId());
        role.setDel(false);
        role = roleRepository.save(role);

        roleDTO = roleMapperExpand.toDTO(role);
        roleDTO = roleMapperExpand.getAgencyInfo(roleDTO);
        roleDTO = roleMapperExpand.getCURDUserInfo(roleDTO);
        return ResultCommon.success().setData(roleDTO);
    }

    /**
     * 查询角色详细信息
     * @param roleId
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(readOnly = true)
    public ResultCommon<SysBaseRoleDTO> search(Long roleId) throws Exception {
        Optional<SysBaseRole> roleOptional = roleRepository.findById(roleId);
        if(!roleOptional.isPresent()){
            return ResultCommon.fail("角色信息不存在");
        }
        SysBaseRole role = roleOptional.get();

        SysBaseRoleDTO roleDTO = roleMapperExpand.toDTO(role);
        roleDTO = roleMapperExpand.getCURDUserInfo(roleDTO);
        roleDTO = roleMapperExpand.getAgencyInfo(roleDTO);
        return ResultCommon.success().setData(roleDTO);
    }

    /**
     * 查询机构下角色列表
     * @param agencyCode 机构编号
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<List<SysBaseRoleDTO>> search(String agencyCode) throws Exception {
        Optional<SysBaseAgency> agencyOptional = agencyRepository.findById(agencyCode);
        if(!agencyOptional.isPresent()){
            return ResultCommon.fail("机构不存在");
        }
        SysBaseAgency agency = agencyOptional.get();
        if(agency.isCancel()){
            return ResultCommon.fail("机构已删除");
        }
        if(agency.isDel()){
            return ResultCommon.fail("机构已注销");
        }

        List<SysBaseRole> roleList = roleRepository.findAllByAgencyCodeAndDelIsFalse(agencyCode);

        return ResultCommon.success().setData(roleMapperExpand.toDTO(roleList));
    }

    /**
     * 查询部门下角色列表
     * @param groupId 部门ID
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<List<SysBaseRoleDTO>> searchofGroup(Long groupId) throws Exception {
        Optional<SysBaseGroup> groupOptional = groupRepository.findById(groupId);
        if(!groupOptional.isPresent()){
            return ResultCommon.fail("部门不存在");
        }
        SysBaseGroup group = groupOptional.get();
        if(group.isDel()){
            return ResultCommon.fail("部门已删除");
        }
        List<SysBaseGr> grs = grRepository.findAllByGroupIdAndDelIsFalse(groupId);
        if(grs!=null && !grs.isEmpty()){
            List<SysBaseRoleDTO> roleList = grs.stream().map(sysBaseGr -> {
                Optional<SysBaseRole> roleOptional = roleRepository.findById(sysBaseGr.getRoleId());
                if(roleOptional.isPresent()){
                    SysBaseRole role = roleOptional.get();
                    if(!role.isDel()){
                        return roleMapperExpand.toDTO(role);
                    }
                }
                return null;
            }).collect(Collectors.toList());
            return ResultCommon.success().setData(roleList);
        }
        return ResultCommon.success();
    }

    /**
     * 查询用户拥有的部门职务
     * @param userId 用户ID
     * @param groupId 部门ID
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<List<SysBaseRoleDTO>> searchofUser(Long userId, Long groupId) throws Exception {
        List<SysBaseUr> urList = urRepository.findAllByUserIdAndGroupIdAndDelIsFalse(userId, groupId);
        if(urList!=null && !urList.isEmpty()){
            List<SysBaseRoleDTO> roleDTOList = urList.stream().map(sysBaseUr -> {
                Optional<SysBaseRole> roleOptional = roleRepository.findById(sysBaseUr.getRoleId());
                if(roleOptional.isPresent()){
                    SysBaseRole role = roleOptional.get();
                    if(!role.isDel()){
                        return roleMapperExpand.toDTO(role);
                    }
                }
                return null;
            }).collect(Collectors.toList());
            return ResultCommon.success().setData(roleDTOList);
        }
        return ResultCommon.success();
    }

    /**
     * 更新角色信息
     * @param roleDTO
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<SysBaseRoleDTO> update(SysBaseRoleDTO roleDTO, AuthoInfoCenter authoInfoCenter) throws Exception {
        EvaluateInfo evaluateInfo = evaluate(roleDTO, roled -> {
            SysBaseRoleDTO roleDTO1 = (SysBaseRoleDTO) roled;
            Optional<SysBaseRole> roleOptional = roleRepository.findById(roleDTO1.getId());
            if(!roleOptional.isPresent()){
                return new EvaluateInfo(false, "角色不存在");
            }
            SysBaseRole role = roleOptional.get();
            if(role.isDel()){
                return new EvaluateInfo(false, "角色已删除");
            }
            Optional<SysBaseAgency> agencyOptional = agencyRepository.findById(roleDTO1.getAgencyCode());
            if(!agencyOptional.isPresent()){
                return new EvaluateInfo(false, "机构不存在");
            }
            SysBaseAgency agency = agencyOptional.get();
            if(agency.isDel()){
                return new EvaluateInfo(false, "机构已删除");
            }
            if(agency.isCancel()){
                return new EvaluateInfo(false, "机构已注销");
            }
            SysBaseRole role1 = roleRepository.findFirstByRoleNameAndAgencyCode(roleDTO1.getRoleName(), roleDTO1.getAgencyCode());
            if(role1 != null){
                return new EvaluateInfo(false, "机构已存在该角色");
            }
            return new EvaluateInfo(true, null);
        });
        if(!evaluateInfo.isSuccess()){
            return ResultCommon.fail(evaluateInfo.getMsg());
        }

        SysBaseRole role = roleMapperExpand.toEntity(roleDTO);
        role.setLastUpdateTime(new Date());
        role.setLastUpdateUser(authoInfoCenter.getUserId());
        role = roleRepository.save(role);

        roleDTO = roleMapperExpand.toDTO(role);
        roleDTO = roleMapperExpand.getAgencyInfo(roleDTO);
        roleDTO = roleMapperExpand.getCURDUserInfo(roleDTO);
        return ResultCommon.success().setData(roleDTO);
    }

    /**
     * 删除角色信息
     * @param roleIds 角色ID列表
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon delete(List<Long> roleIds, AuthoInfoCenter authoInfoCenter) throws Exception {
        for(Long roleId:roleIds){
            Optional<SysBaseRole> roleOptional = roleRepository.findById(roleId);
            if(!roleOptional.isPresent()){
                throw new Exception(roleId+"角色不存在");
            }
            SysBaseRole role = roleOptional.get();
            role.setDel(true);
            role.setDelTime(new Date());
            role.setDelUser(authoInfoCenter.getUserId());
            role = roleRepository.save(role);
        }
        return ResultCommon.success();
    }

    /**
     * 分页查询角色信息
     * @param page 页码
     * @param limit 条数
     * @param agencyCode 机构编号
     * @param roleName 角色名称
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(readOnly = true)
    public ResultCommon<PageData<SysBaseRoleDTO>> page(int page, int limit, String agencyCode, String roleName) throws Exception {
        Specification<SysBaseRole> specification = new Specification<SysBaseRole>() {
            @Override
            public Predicate toPredicate(Root<SysBaseRole> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();

                Predicate predicate1 = criteriaBuilder.equal(root.get("agencyCode"), agencyCode);
                predicateList.add(predicate1);

                if(!StringUtils.isEmpty(roleName)){
                    Predicate predicate = criteriaBuilder.like(root.get("roleName"), roleName+"%");
                    predicateList.add(predicate);
                }
                Predicate predicate = criteriaBuilder.isFalse(root.get("del"));
                predicateList.add(predicate);
                Predicate[] predicates = new Predicate[predicateList.size()];
                return criteriaBuilder.and(predicateList.toArray(predicates));
            }
        };

        Pageable pageable = PageRequest.of(page-1, limit, Sort.by(Sort.Order.asc("id")));
        Page<SysBaseRole> rolePage = roleRepository.findAll(specification, pageable);
        List<SysBaseRoleDTO> roleDTOS = rolePage.get().map(sysBaseRole -> {
            SysBaseRoleDTO roleDTO = roleMapperExpand.toDTO(sysBaseRole);
            roleDTO = roleMapperExpand.getAgencyInfo(roleDTO);
            roleDTO = roleMapperExpand.getCURDUserInfo(roleDTO);
            return roleDTO;
        }).collect(Collectors.toList());
        return ResultCommon.success().setData(new PageData<SysBaseRoleDTO>(page, limit,
                Long.valueOf(rolePage.getTotalElements()).intValue(), roleDTOS));
    }

    /**
     * 数据检校
     * @param evaluateMethod
     * @return
     */
    private EvaluateInfo evaluate(Object obj, EvaluateMethod<Object> evaluateMethod){

        return evaluateMethod.evaluate(obj);
    }
}
